include std/dll.e
include std/machine.e
include std/convert.e

include core.e
include wrap_helpers.e

constant
	hQt_addDataBase = define_c_func(hEuQt, "qt_db_addDatabase", {CP, CP}, I),
	hQt_removeDatabase = define_c_func(hEuQt, "qt_db_removeDatabase", {CP}, I),
	hQt_lastError = define_c_func(hEuQt, "qt_db_lastError", {CP}, CP),
	hQt_isDriverAvailable = define_c_func(hEuQt, "qt_db_isDriverAvailable", {CP}, I),
	hQt_DriversAvailable = define_c_func(hEuQt, "qt_db_DriversAvailable", {CP}, CP),
	hQt_isDataBaseAvailable = define_c_func(hEuQt, "qt_db_isDataBaseAvailable", {CP}, I),
	
	hQt_transaction = define_c_func(hEuQt, "qt_db_transaction", {CP}, I),
	hQt_rollback = define_c_func(hEuQt, "qt_db_rollback", {CP}, I),
	hQt_commit = define_c_func(hEuQt, "qt_db_commit", {CP}, I),
	hQt_isOpenError = define_c_func(hEuQt, "qt_db_isOpenError", {CP}, I),
	hQt_isOpen = define_c_func(hEuQt, "qt_db_isOpen", {CP}, I),

	hQt_Query = define_c_func(hEuQt, "qt_db_Query", {CP}, P),
	hQt_exec = define_c_func(hEuQt, "qt_db_exec", {P, CP}, I),
	hQt_isActive = define_c_func(hEuQt, "qt_db_isActive", {P}, I),
	hQt_isValid = define_c_func(hEuQt, "qt_db_isValid", {P}, I),
	hQt_first = define_c_func(hEuQt, "qt_db_first", {P}, I),
	hQt_next = define_c_func(hEuQt, "qt_db_next", {P}, I),
	hQt_last = define_c_func(hEuQt, "qt_db_last", {P}, I),
	hQt_previous = define_c_func(hEuQt, "qt_db_previous", {P}, I),
	hQt_isForwardOnly = define_c_func(hEuQt, "qt_db_isForwardOnly", {P}, I),
	hQt_setForwardOnly = define_c_proc(hEuQt, "qt_db_setForwardOnly", {P, I}),
	hQt_isSelect = define_c_func(hEuQt, "qt_db_isSelect", {P}, I),
	
	hQt_isNull = define_c_func(hEuQt, "qt_db_isNull", {P, I}, I),
	hQt_seek = define_c_func(hEuQt, "qt_db_seek", {P, I}, I),
	hQt_value = define_c_func(hEuQt, "qt_db_value", {P, I}, CP),
	$

--****
--  experimental and or not fully implemented/tested at this point...
--
-- wraps the QtSql routines to manage and use a database. the compiling
-- of Qt libs will determine which database plugins or builtins are available. 
--which might include mySql Sqlite PSgre?  the Qt docs are a little fuzzty.
--possibly QSQLITE will be available by default as a builtin.
---ODBC connectivity is another fallback and slower posibility
--you will also need the database libs themselves for the others.
--see the Qt database docs, there are many limitations and notes.
--
--<<LEVELTOC depth=2>>
--
-- === Driver types
-- ||Driver ||Type ||Description ||
-- |QDB2 |IBM DB2|  |
-- |QIBASE |Borland InterBase |Driver  |
-- |QMYSQL |MySQL |Driver  |
-- |QOCI |Oracle Call Interface |Driver  |
-- |QODBC |ODBC |Driver (includes Microsoft SQL Server) |
-- |QPSQL |PostgreSQL |Driver  |
-- |QSQLITE |SQLite version 3 or above | |
-- |QSQLITE2 |SQLite version 2 | |
-- |QTDS |Sybase Adaptive Server | |
-- 
-- reminder, not all database drivers will be available to everyone on every system
--unless you are sure, the safest choice is probably QSQLITE.
-- you can try more than one and the rest of the routines should just work.
-- unless there are no drivers available.
-- !!why is there no flat file driver worstcase fallback?
--To force SQLite to use a specific file format, it is neccessary to build and ship your own database plugin with your own SQLite library 
-- 
--there will be a function to list and return valid path to plugins at runtime..


--****
-- === Routines

--**
-- if dbplugin is empty return a coma seperated list of all database plugins
-- otherwise returns a true/false if the named plugin is available
public function db_available(sequence dbplugin="", sequence dbname="")
	atom pname = allocate_string(dbplugin,1)
	--~ atom pdbname = allocate_string(dbname,1)

	atom result = c_func(hQt_isDriverAvailable, {pname})
	return result
end function

--**
--dbplugin is one of QSQLLITE or QODBC or if compiled into Qt MYSQL etc
-- if dbname is empty, use default database.
-- SQLite also supports in-memory databases, simply pass ":memory:" as the database name.

public function db_addDatabase(object dbplugin, object dbname="")
	atom pname = allocate_string(dbplugin,1)
	atom pdbname = allocate_string(dbname,1)

	atom result = c_func(hQt_addDataBase, {pname, pdbname})
	return result
end function

--**
--
public function db_removeDatabase(object dbname="")
	atom pname = allocate_string(dbname,1)
	atom result = c_func(hQt_removeDatabase, {pname})
	return result
end function

--**
--return last error on named database or last error on default database
public function db_lastError(object dbname="")
	atom pname = allocate_string(dbname,1)
	atom result = c_func(hQt_lastError, {pname})
	return peek_string(result )
end function

--**
--
public function db_transaction(object dbname="")
	atom pname = allocate_string(dbname,1)
	return c_func(hQt_transaction, {pname})
end function

--**
--
public function db_rollback(object dbname="")
	atom pname = allocate_string(dbname,1)
	return c_func(hQt_rollback, {pname})
end function

--**
--
public function db_commit(object dbname="")
	atom pname = allocate_string(dbname,1)
	return c_func(hQt_commit, {pname})
end function

--**
--
public function db_isOpenError(object dbname="")
	atom pname = allocate_string(dbname,1)
	return c_func(hQt_isOpenError, {pname})
end function

--**
--
public function db_isOpen(object dbname="")
	atom pname = allocate_string(dbname,1)
	return c_func(hQt_isOpen, {pname})
end function


--**
--acts on the currently opened database?
--~ QSqlQuery ( QSqlResult * result ) 
--~ QSqlQuery ( const QString & query = QString(), QSqlDatabase db = QSqlDatabase() ) 
--~ QSqlQuery ( QSqlDatabase db ) 
--~ QSqlQuery ( const QSqlQuery & other ) 



public function db_Query(object q="")
	atom pq = allocate_string(q,1)

	atom result = c_func(hQt_Query, {pq})
	return result
end function

--**
--acts on the currently opened database? with atom query returned from db_Query()

public function db_exec(atom query, sequence q="")
	atom pq = allocate_string(q,1)

	integer result = c_func(hQt_exec, {query,pq})
	return result
end function

public function db_isActive(atom query)
	return c_func(hQt_isActive, {query})
end function

public function db_isValid(atom query)
	return c_func(hQt_isValid, {query})
end function

public function db_isForwardOnly(atom query)
	return c_func(hQt_isForwardOnly, {query})
end function

public procedure db_setForwardOnly(atom query, integer forward=1)
	c_proc(hQt_setForwardOnly, {query, forward })
end procedure


public function db_isSelect(atom query)
	return c_func(hQt_isSelect, {query})
end function


public function db_isNull(atom query, atom field)
	return c_func(hQt_isNull, {query, field})
end function
 
public function db_first(atom query)
	return c_func(hQt_first, {query})
end function

public function db_next(atom query)
	return c_func(hQt_next, {query})
end function

public function db_last(atom query)
	return c_func(hQt_last, {query})
end function

public function db_previous(atom query)
	return c_func(hQt_previous, {query})
end function



public function db_seek(atom query, atom index)
	return c_func(hQt_seek, {query, index})
end function


--**
--varchar only right now
public function db_value(atom query, atom index)
	atom result = c_func(hQt_value, {query, index})
	return peek_string(result )
end function



--possibly start or add mock functions for QSql and QXml to return true
--or false based on imit mock functions so you can easily test some logic
--without the overhead of creating and changing real databases on disk or remote
 --the in memory db is good, but will fail for very large test data eventually and be slower than a mock

